﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using Proggy.Web.Cms.Repositories.Membership;
using System.Web;
using Proggy.Web.Cms.Context;
using System.Web.Configuration;

namespace Proggy.Web.Cms.Membership
{
    /// <summary>
    /// Authorize - broad-brush strokes - sets membership context, can use to restrict controllers or actions to 
    /// specific groups to
    /// </summary>
    public class ProggyBackEndAuthorizeAttribute : AuthorizeAttribute
    {
        /// <summary>
        /// Group constructor - sets membership context and checks user against groups
        /// NOTE: no need to add "back end user" or "global admin" as they will already be set by default
        /// </summary>
        /// <param name="lowercaseCommaSeparatedGroups"></param>
        public ProggyBackEndAuthorizeAttribute(string lowercaseCommaSeparatedGroups)
        {
            // get groups
            this._groups =
                 lowercaseCommaSeparatedGroups != null && lowercaseCommaSeparatedGroups.Contains(",") ?
                     lowercaseCommaSeparatedGroups.Split(',') :
                     new string[] { lowercaseCommaSeparatedGroups };

            // set repo
            this._repo = DependencyResolver.Current.GetService<IMembershipRepository>();
        }

        /// <summary>
        /// Constructor which  only locks down to "back end user" / "global admin"
        /// </summary>
        public ProggyBackEndAuthorizeAttribute()
        {
            // set repo
            this._repo = DependencyResolver.Current.GetService<IMembershipRepository>();
        }

        /// <summary>
        /// Private
        /// </summary>
        private IMembershipRepository _repo;

        /// <summary>
        /// The group string array
        /// </summary>
        private string[] _groups;

        /// <summary>
        /// Authorize
        /// </summary>
        /// <param name="httpContext"></param>
        /// <returns></returns>
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            // check
            if (httpContext.Request.IsAuthenticated)
            {
                // check
                if (this._groups != null)
                {
                    // add to groups
                    var list = this._groups.ToList();
                    //list.Add(MembershipConstants.GLOBAL_ADMIN_GROUP_NAME);
                    //list.Add(MembershipConstants.BACK_END_USER_GROUP_NAME);
                    this._groups = list.ToArray();
                }
                else
                {
                    this._groups = new string[] { 
                    //MembershipConstants.BACK_END_USER_GROUP_NAME,
                    //MembershipConstants.GLOBAL_ADMIN_GROUP_NAME
                };

                }

                // get ok
                return this._repo.GetAuthOk(MembershipContext.Current.CurrentMember, _groups.Distinct().ToArray());
            }
            else
            {
                return base.AuthorizeCore(httpContext);
            }

        }

        /// <summary>
        /// Handle unauthorized
        /// </summary>
        /// <param name="filterContext"></param>
        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            // check
            if (MembershipContext.CurrentAuthenticationMode == AuthenticationMode.Windows)
            {
                throw new HttpException(403, "Access denied");
            }
            else
            {
                // check logged in
                if (filterContext.HttpContext.Request.IsAuthenticated)
                {
                    // logged in, so not allowed
                    throw new HttpException(403, "Access denied");
                }

                // redirect to back-end login
                filterContext
                    .HttpContext
                    .Response
                    .Redirect(
                        FrontEndRequestContext.GetRootUrl() +
                        "Proggy/FormsAuthentication/Logon?returnUrl=" +
                        HttpUtility.UrlEncode(filterContext.HttpContext.Request.Path),
                        true);
            }
        }
    }
}
